import { CODE } from "./constants.js";
import { catch_error_resp } from "./request.js";

/*
 * 测试脚本执行方法：
 * 1. 终端进入脚本所在文件夹，执行 `npm init -y`（快速生成 package.json）
 * 2. 打开 package.json，添加 `"type": "module"`（关键配置），示例：
 *      {
 *        "name": "sse-test",
 *        "version": "1.0.0",
 *        "type": "module", // 必须添加，否则 import 报错
 *        "main": "当前脚本文件名.js" // 替换为实际脚本名（如 sse-test.js）
 *     }
 * 3. node sse-test.js
 */

const concurrency = 1000
const test_times = 3

const url = "http://localhost:8000/api/v1/chat/ai/completions"
const chatDialog = { // 从数据库随便拷一个
  "id": "68c573f58af546d70967c123",
  "name": "test1",
  "lastActiveAt": 0,
  "assistantId": "68c573d3b4857c17c23fab9a",
  "userId": 1,
  "requestId": "8f6e67c4-fc42-4918-b3e6-36ef1797d01e"
}
const chatMsg = "用更通俗移动的方式，向我介绍下StableAvatar的原理，以及为什么会有效果"
const token = {'Authorization': "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODk0Mzg5ODAsImlhdCI6MTc1NzkwMjk4MCwiand0VXNlcklkIjoxfQ.5TCxhCRE997gHbJfne4Qma7zCrkYl26xhjCWYgluMlU"}

class MockChatStream {
    #url;
    #controller;
    // 新增 promise 用于追踪请求完成状态
    #requestPromise;

    constructor(url) {
        this.#url = url;
        this.#controller = null;
        this.onMessage = () => {};
        this.onFinish = () => {};
        this.onError = (error) => {
            console.error(`[请求失败]`, error);
        };
    }

    async send({ chatMsg, chatDialog }) {
        // 返回 promise 并赋值给 #requestPromise，用于外部追踪状态
        this.#requestPromise = new Promise(async (resolve, reject) => {
            this.#controller = new AbortController();
            let reader;

            try {
                const response = await fetch(this.#url, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Accept": "text/event-stream",
                    // 修复 token 传递格式：取对象的 Authorization 属性值
                    "Authorization": token.Authorization
                },
                body: JSON.stringify({
                    "chatMsg": chatMsg,
                    "chatDialog": chatDialog,
                    "isNew": false,
                }),
                signal: this.#controller.signal
                });

                // 检查响应状态码，非 200 直接视为错误
                if (!response.ok) {
                throw new Error(`HTTP 错误: ${response.status} ${response.statusText}`);
                }

                reader = response.body.getReader();
                const decoder = new TextDecoder();

                while (true) {
                  const { done, value } = await reader.read();
                  if (done) {
                      this.onFinish();
                      resolve("请求正常完成"); // 标记请求成功
                      break;
                  }
                  const chunk = decoder.decode(value);
                  chunk.split('\n\n').forEach(event => {
                      if (event.startsWith('data:')) {
                      const data = event.replace('data:', '').trim();
                      this.onMessage(data);
                      }
                  });
                }
            } catch (err) {
                if (err.name === "AbortError") {
                reject("请求被主动中断");
                return;
                }
                this.abort()
                let error_resp;
                if (err instanceof SyntaxError) {
                console.error("ChatStream send: 解析失败:", err);
                error_resp = { code: CODE.SERVER_COMMON_ERROR, msg: `解析后端返回数据格式失败` };
                } else {
                error_resp = catch_error_resp(err) || { code: CODE.SERVER_COMMON_ERROR, msg: err.message };
                }
                this.onError(error_resp);
                reject(error_resp); // 标记请求失败
            } finally {
                reader?.releaseLock();
                this.#controller = null;
            }
        });

        // 返回 promise，允许外部 await
        return this.#requestPromise;
    }

    isChating() {
        return this.#controller !== null
    }

    abort() {
        if(this.isChating()) {
            this.#controller.abort();
        }
    }

    // 新增：获取请求的 promise，用于等待请求完成
    getRequestPromise() {
        return this.#requestPromise;
    }
}

// 3. 核心测试函数（支持并行、时间统计、等待所有请求完成）
async function runSSETests() {
  console.log(`[测试开始] 并行数: ${concurrency}, 接口: ${url}`);
  const startTime = Date.now(); // 记录开始时间
  const testPromises = []; // 存储所有请求的 promise，用于等待全部完成

  try {
    // 创建并行请求
    for (let i = 0; i < concurrency; i++) {
      // 发起请求并将 promise 加入数组
      const test_loop = async () => {
        const chater = new MockChatStream(url);
        // 自定义当前请求的回调（可选，便于区分不同并行请求）
        // chater.onMessage = (data) => {
        //   console.log(`[并行请求 ${i + 1}/${concurrency}] 接收消息`, data);
        // };
        // chater.onFinish = () => {
        //   console.log(`[并行请求 ${i + 1}/${concurrency}] 完成`);
        // };
        chater.onError = (error) => {
          console.error(`[并行请求 ${i + 1}/${concurrency}] 失败:`, error);
        };
        for (let j = 0; j < test_times; j++) {
          await chater.send({
            chatMsg: {
                id: `my-test ${i}-${j}`,
                content: chatMsg,
                role: 'user',
                chatAt: Math.floor(Date.now() / 1000),
                dialogID: chatDialog.id,
                requestId: "123",
            },
            chatDialog: chatDialog
          });
        }
      }
      const requestPromise = test_loop()
      testPromises.push(requestPromise);
    }

    // 等待所有并行请求完成（无论成功/失败，用 Promise.allSettled）
    const results = await Promise.allSettled(testPromises);

    // 统计结果
    const successCount = results.filter(res => res.status === "fulfilled").length;
    const failCount = results.filter(res => res.status === "rejected").length;
    const endTime = Date.now();
    const totalTime = (endTime - startTime) / 1000; // 转换为秒

    // 打印最终统计信息
    console.log("\n" + "=".repeat(50));
    console.log(`[测试结束] 总耗时: ${totalTime.toFixed(2)} 秒`);
    console.log(`[结果统计] 成功: ${successCount} 个, 失败: ${failCount} 个`);
    console.log("=".repeat(50));

    // 若有失败，打印失败详情
    if (failCount > 0) {
      console.log("\n[失败详情]");
      results.forEach((res, index) => {
        if (res.status === "rejected") {
          console.log(`请求 ${index + 1}:`, res.reason);
        }
      });
    }

  } catch (globalErr) {
    // 捕获全局异常（如创建实例失败）
    console.error(`[全局错误] 测试执行异常:`, globalErr);
    const endTime = Date.now();
    const totalTime = (endTime - startTime) / 1000;
    console.log(`[测试中断] 总耗时: ${totalTime.toFixed(2)} 秒`);
  }
}

// 4. 执行测试（调用入口）
await runSSETests(); // 等待所有测试完成（SSE 连接、数据接收、结果统计）
console.log("所有测试已完全结束，脚本退出");